package com.cskaoyan.javase.thread._4synchronized._1impl.static0;

/**
 * 静态同步方法,就是synchronized关键字修饰的静态成员方法
 * [访问权限修饰符] static 返回值类型 方法名(形参){
 *     // 方法
 * }
 * 解释:
 *      1.整个静态同步方法就是一个原子操作
 *      2.它也有锁对象,锁对象是该类的字节码Class对象
 *
 * 在类加载的过程中,JVM会在堆上创建一个封装了该类类型信息的Class对象
 *
 * 如何获取Class对象呢?
 *      1.成员方法getClass
 *
 * @since 16:20
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        SellTicketTask task = new SellTicketTask();
        Thread t1 = new Thread(task, "窗口1");
        Thread t2 = new Thread(task, "窗口2");
        Thread t3 = new Thread(task, "窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}

class SellTicketTask implements Runnable {
    private static int ticketNum = 1;

    @Override
    public void run() {
        long start = System.currentTimeMillis();
        // 使用同步代码块保证多线程环境下的数据安全
        while (System.currentTimeMillis() - start < 10000) {
            if (ticketNum % 2 == 0) {
                // 偶数票,用同步代码块加锁保证线程同步
                synchronized (new SellTicketTask().getClass()) {
                    if (ticketNum <= 100) {
                        // 每次卖出一张票,休眠一段时间,模拟卖票需要耗费一点时间
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "卖出了第" + ticketNum + "张票!");
                        ticketNum++;
                    }
                }
            } else {
                // 奇数票
                sellTicket();
            }
        }
    }

    // 将卖票抽取为一个方法,定义成同步方法,卖票整个操作都变成了一个原子操作
    private static synchronized void sellTicket() {
        if (ticketNum <= 100) {
            // 每次卖出一张票,休眠一段时间,模拟卖票需要耗费一点时间
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "卖出了第" + ticketNum + "张票!");
            ticketNum++;
        }
    }
}